package rfc8009

import (
	
	
	
	

	
	
	
)

const (
	s2kParamsZero = 32768
)

// DeriveRandom for key derivation as defined in RFC 8009
func (,  []byte,  etype.EType) ([]byte, error) {
	 := .GetHashFunc()()
	return KDF_HMAC_SHA2(, []byte("prf"), , .Size(), ), nil
}

// DeriveKey derives a key from the protocol key based on the usage and the etype's specific methods.
//
// https://tools.ietf.org/html/rfc8009#section-5
func (,  []byte,  etype.EType) []byte {
	var  []byte
	var  int
	// Key length is longer for aes256-cts-hmac-sha384-192 is it is a Ke or from StringToKey (where label is "kerberos")
	if .GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
	:
		switch [len()-1] {
		case 0x73:
			// 0x73 is "s" so label could be kerberos meaning StringToKey so now check if the label is "kerberos"
			 := []byte("kerberos")
			if len() != len() {
				break
			}
			for ,  := range  {
				if  != [] {
					 = .GetKeySeedBitLength()
					break 
				}
			}
			if  == 0 {
				// This is StringToKey
				 = 256
			}
		case 0xAA:
			// This is a Ke
			 = 256
		}
	}
	if  == 0 {
		 = .GetKeySeedBitLength()
	}
	return .RandomToKey(KDF_HMAC_SHA2(, , , , ))
}

// RandomToKey returns a key from the bytes provided according to the definition in RFC 8009.
func ( []byte) []byte {
	return 
}

// StringToKey returns a key derived from the string provided according to the definition in RFC 8009.
func (, ,  string,  etype.EType) ([]byte, error) {
	,  := S2KparamsToItertions()
	if  != nil {
		return nil, 
	}
	return StringToKeyIter(, , , )
}

// StringToKeyIter returns a key derived from the string provided according to the definition in RFC 8009.
func (,  string,  int,  etype.EType) ([]byte, error) {
	 := .RandomToKey(StringToPBKDF2(, , , ))
	return .DeriveKey(, []byte("kerberos"))
}

// StringToPBKDF2 generates an encryption key from a pass phrase and salt string using the PBKDF2 function from PKCS #5 v2.0
func (,  string,  int,  etype.EType) []byte {
	 := .GetKeyByteSize()
	if .GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
		 = 32
	}
	return pbkdf2.Key([]byte(), []byte(), , , .GetHashFunc())
}

// KDF_HMAC_SHA2 key derivation: https://tools.ietf.org/html/rfc8009#section-3
func (, ,  []byte,  int,  etype.EType) []byte {
	//k: Length in bits of the key to be outputted, expressed in big-endian binary representation in 4 bytes.
	 := make([]byte, 4, 4)
	binary.BigEndian.PutUint32(, uint32())

	 := make([]byte, 4, 4)
	binary.BigEndian.PutUint32(, uint32(1))
	 = append(, ...)
	 = append(, byte(0))
	if len() > 0 {
		 = append(, ...)
	}
	 = append(, ...)

	 := hmac.New(.GetHashFunc(), )
	.Write()
	return .Sum(nil)[:( / 8)]
}

// GetSaltP returns the salt value based on the etype name: https://tools.ietf.org/html/rfc8009#section-4
func (,  string) string {
	 := []byte()
	 = append(, byte(0))
	 = append(, []byte()...)
	return string()
}

// S2KparamsToItertions converts the string representation of iterations to an integer for RFC 8009.
func ( string) (int, error) {
	var  uint32
	if len() != 8 {
		return s2kParamsZero, errors.New("Invalid s2kparams length")
	}
	,  := hex.DecodeString()
	if  != nil {
		return s2kParamsZero, errors.New("Invalid s2kparams, cannot decode string to bytes")
	}
	 = binary.BigEndian.Uint32()
	//buf := bytes.NewBuffer(b)
	//err = binary.Read(buf, binary.BigEndian, &i)
	if  != nil {
		return s2kParamsZero, errors.New("Invalid s2kparams, cannot convert to big endian int32")
	}
	return int(), nil
}